package com.zmn.oms.business.impl.xno;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerBasicInfoDRO;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.business.interfaces.xno.OrderXnoBindService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.MobileUtil;
import com.zmn.oms.model.dto.work.masterwork.DelayBindDTO;
import com.zmn.oms.model.dto.work.xno.XnoBindDTO;
import com.zmn.oms.model.dto.work.xno.XnoUnBindDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.work.detail.ZsXnoBindVO;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.base.plat.engine.common.constant.DubboConsts;
import com.zmn.xno.dubbo.interfaces.bind.AxbBindRemoteService;
import com.zmn.xno.dubbo.model.bind.*;
import com.zmn.xno.model.entity.bind.XnoBind;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Objects;


/**
 * @author ：SongWeidong
 * @date ：2020/6/8 18:03
 * @description：小号相关操作
 */
@Service
@Slf4j
public class OrderXnoBindServiceImpl implements OrderXnoBindService {

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private AreaListRemoteService areaListRemoteService;
    @DubboReference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerListRemoteService engineerListRemoteService;
    //@Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    //private BaseInfoListRemoteService baseInfoListRemoteService;
    @DubboReference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private AxbBindRemoteService axbBindRemoteService;

    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderWorkService orderWorkService;

    /**
     * 绑定小号
     *
     * @return
     */
    @Override
    public void bind(XnoBindDTO xnoBindDTO){
        try {
            OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(xnoBindDTO.getOrderId(), xnoBindDTO.getWorkId());

            log.info("XnoBind-绑定小号：{}", xnoBindDTO);

            // 号码变更，先解除绑定
            if (Objects.nonNull(xnoBindDTO.getUnBindMasterId())) {
                XnoUnBindDTO unBindDTO = new XnoUnBindDTO();
                unBindDTO.setOrderId(orderWork.getOrderId());
                unBindDTO.setWorkId(orderWork.getWorkId());
                unBindDTO.setUnBindMasterId(xnoBindDTO.getUnBindMasterId());
                unBindDTO.setUnBindTelephone1(xnoBindDTO.getUnBindTelephone1());
                unBindDTO.setUnBindTelephone2(xnoBindDTO.getUnBindTelephone2());
                unBindDTO.setUnBindTelephone3(xnoBindDTO.getUnBindTelephone3());
                log.info("XnoBind-绑定小号-先解绑 orderId【{}】", xnoBindDTO.getOrderId());
                this.unBindXno(unBindDTO, orderWork);
            }

            Integer masterId = orderWork.getMasterId();
            if (NumberUtil.isNullOrZero(masterId)) {
                return;
            }

            // 查询师傅手机号
            String masterMobile = null;
            // todo fubiao
            log.info("bind#getEngineerById start [{}]",masterId);
            ResponseDTO<ForeignEngineerBasicInfoDRO> basicInfo = engineerListRemoteService.getEngineerById(masterId);
            log.info("bind#getEngineerById end [{}]",JSON.toJSONString(basicInfo));
            if (basicInfo.getData() != null && basicInfo.isSuccess()) {
                masterMobile = basicInfo.getData().getMobile();
            }
            if (StringUtils.isBlank(masterMobile)) {
                return;
            }

            // 判断电话是否是座机
            String code = "";
            ResponseDTO<AreaDRO> byId = areaListRemoteService.getById(orderWork.getCityId());
            if (byId.isSuccess() && byId.getData() != null) {
                code = byId.getData().getAreaNum();
            }

            OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(xnoBindDTO.getOrderId());

            String firstXno = null;
            String firstXno2 = null;
            String firstXno3 = null;
            // 绑定
            if (xnoBindDTO.getNeedBindFirstXno() != null && xnoBindDTO.getNeedBindFirstXno()) {
                firstXno = orderDetail.getBindTelephone();
                firstXno2 = orderDetail.getBindTelephone2();
                firstXno3 = orderDetail.getBindTelephone3();
            }
            // 过期时间
            String axbBind1 = axbBind(orderWork, masterMobile, code, orderDetail.getTelephone(), firstXno, xnoBindDTO.getExpiredDuration());
            String axbBind2 = axbBind(orderWork, masterMobile, code, orderDetail.getTelephone2(), firstXno2, xnoBindDTO.getExpiredDuration());
            String axbBind3 = axbBind(orderWork, masterMobile, code, orderDetail.getTelephone3(), firstXno3, xnoBindDTO.getExpiredDuration());

            // 设置绑定状态为已绑定
            if (StringUtils.isNotBlank(axbBind1) || StringUtils.isNotBlank(axbBind2) || StringUtils.isNotBlank(axbBind3)) {
                OrderDetail updateOrderDetail = new OrderDetail();
                updateOrderDetail.setDetailId(orderDetail.getDetailId());
                updateOrderDetail.setBindTelephone(axbBind1);
                updateOrderDetail.setBindTelephone2(axbBind2);
                updateOrderDetail.setBindTelephone3(axbBind3);
                updateOrderDetail.setBindStatus(1);
                orderDetailService.updateOrderDetailByKey(updateOrderDetail);
            }
            xnoBindDTO.setBindTelephone1(axbBind1);
            xnoBindDTO.setBindTelephone2(axbBind2);
            xnoBindDTO.setBindTelephone3(axbBind3);
        } catch (OmsBaseException e) {
            xnoBindDTO.setFailCode(e.getCode());
            xnoBindDTO.setFailMessage("小号绑定失败：" + e.getMessage());
            log.info("XnoBind-绑定异常：{}", e.getMessage());
        } catch (Exception e) {
            xnoBindDTO.setFailMessage("小号绑定失败：" + e.getMessage());
            log.info("XnoBind-绑定异常：{}", e.getMessage());
        }
    }

    /**
     * 绑定小号
     *
     * @param orderWork
     * @param engineerPhone
     * @param code
     * @param telephone
     * @param firstXno
     * @param expiredDuration
     * @return
     * @throws OmsBaseException
     */
    private String axbBind(OrderWork orderWork,
                           String engineerPhone,
                           String code,
                           String telephone,
                           String firstXno,
                           Long expiredDuration) throws OmsBaseException {
        if (StringUtils.isBlank(telephone)) {
            return null;
        }

        telephone = MobileUtil.isFixedPhone(telephone) ? code + telephone : telephone;

        // 查询绑定关系，如果已绑定，不进行绑定
        ZsXnoBindVO zsXnoBindVO = this.queryXNO(engineerPhone, telephone, code, orderWork);
        if (zsXnoBindVO != null && Objects.equals(zsXnoBindVO.getStatus(), OrderConsts.BIND_STATUS_BIND)) {
            return zsXnoBindVO.getXno();
        }
        // 设置过期关系
        long bindTime = NumberUtil.isNotNullOrZero(expiredDuration)?expiredDuration:OrderConsts.BIND_TIME;
        AxbBindDIO axb = AxbBindDIO.builder().ano(engineerPhone).appKey("oms").atype(1)
                .bizId(orderWork.getOrderId().toString())
                .bno(telephone)
                .btype(2)
                .plat(orderWork.getPlatWork())
                .cityId(orderWork.getCityId())
                .level1Id(orderWork.getPlatWork())
                .level2Id(orderWork.getManageCompanyId())
                .level3Id(orderWork.getCityId())
                .expiredDuration(bindTime)
                .engineerId(orderWork.getMasterId())
                .engineerName(orderWork.getMasterName())
                .firstXno(firstXno).build();

        log.info("XnoBind-小号绑定接口入参：{}", axb);
        ResponseDTO<AxbBindDRO> bindResponse = axbBindRemoteService.bindX(axb);
        log.info("XnoBind-小号绑定接口出参：orderId :{},{}", axb.getBizId(), JSONObject.toJSONString(bindResponse));
        if (bindResponse.getData() != null && bindResponse.isSuccess()) {
            AxbBindDRO bindDRO = bindResponse.getData();
            return bindDRO.getXno();
        }
        if (bindResponse.getData() != null) {
            throw new OmsBaseException(Integer.valueOf(bindResponse.getData().getCode()), bindResponse.getMessage());
        }
        throw new OmsBaseException(bindResponse.getStatus(), bindResponse.getMessage());
    }

    @Override
    public void unBind(XnoUnBindDTO xnoUnBindDTO) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(xnoUnBindDTO.getOrderId(), xnoUnBindDTO.getWorkId());
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(xnoUnBindDTO.getOrderId());
        xnoUnBindDTO.setOrderId(orderWork.getOrderId());
        xnoUnBindDTO.setWorkId(orderWork.getWorkId());
        if (Objects.isNull(xnoUnBindDTO.getUnBindMasterId())) {
            xnoUnBindDTO.setUnBindMasterId(orderWork.getMasterId());
        }
        xnoUnBindDTO.setUnBindTelephone1(orderDetail.getTelephone());
        xnoUnBindDTO.setUnBindTelephone2(orderDetail.getTelephone2());
        xnoUnBindDTO.setUnBindTelephone3(orderDetail.getTelephone3());
        try {
            this.unBindXno(xnoUnBindDTO, orderWork);

            // 设置状态为解绑成功
            OrderDetail unOrderDetail = new OrderDetail();
            unOrderDetail.setDetailId(xnoUnBindDTO.getOrderId());
            unOrderDetail.setBindStatus(OrderConsts.BIND_STATUS_UNBIND);
            orderDetailService.updateOrderDetailByKey(unOrderDetail);
            xnoUnBindDTO.setBindStatus(OrderConsts.BIND_STATUS_UNBIND);

            log.info("XnoBind-解绑成功->{}", JSON.toJSONString(xnoUnBindDTO));
        } catch (OmsBaseException ex) {
            xnoUnBindDTO.setOperatorLogRemark("小号解绑失败：" + ex.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            xnoUnBindDTO.setOperatorLogRemark("小号解绑失败");
        }
    }

    @Override
    public void unBindAll(XnoUnBindDTO xnoUnBindDTO) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(xnoUnBindDTO.getOrderId(), xnoUnBindDTO.getWorkId());
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(xnoUnBindDTO.getOrderId());

        xnoUnBindDTO.setOrderId(orderWork.getOrderId());
        xnoUnBindDTO.setWorkId(orderWork.getWorkId());
        xnoUnBindDTO.setUnBindMasterId(orderWork.getMasterId());
        xnoUnBindDTO.setUnBindTelephone1(orderDetail.getTelephone());
        xnoUnBindDTO.setUnBindTelephone2(orderDetail.getTelephone2());
        xnoUnBindDTO.setUnBindTelephone3(orderDetail.getTelephone3());
        try {
            this.unBindXno(xnoUnBindDTO, orderWork);
            log.info("XnoBind-unBindAll-解绑成功->{}", JSON.toJSONString(xnoUnBindDTO));
        } catch (OmsBaseException ex) {
            xnoUnBindDTO.setOperatorLogRemark("小号解绑失败：" + ex.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            xnoUnBindDTO.setOperatorLogRemark("小号解绑失败");
        }

        // 设置状态为解绑成功
        OrderDetail unOrderDetail = new OrderDetail();
        unOrderDetail.setDetailId(xnoUnBindDTO.getOrderId());
        unOrderDetail.setBindStatus(OrderConsts.BIND_STATUS_UNBIND);
        orderDetailService.updateOrderDetailByKey(unOrderDetail);
    }

    /**
     * 解绑小号
     *
     * @return
     */
    private void unBindXno(XnoUnBindDTO xnoUnBindDTO, OrderWork orderWork) throws OmsBaseException {
        if (NumberUtil.isNullOrZero(xnoUnBindDTO.getUnBindMasterId())) {
            xnoUnBindDTO.setBindStatus(GlobalConsts.NONE);
            return;
        }

        // 查询师傅手机号
        String engineerPhone = null;
        // todo fubiao
        log.info("unBindXno#getEngineerById start [{}]",xnoUnBindDTO.getUnBindMasterId());
        ResponseDTO<ForeignEngineerBasicInfoDRO> basicInfo = engineerListRemoteService.getEngineerById(xnoUnBindDTO.getUnBindMasterId());
        log.info("unBindXno#getEngineerById end [{}]",JSON.toJSONString(basicInfo));
        if (basicInfo.getData() != null && basicInfo.isSuccess()) {
            engineerPhone = basicInfo.getData().getMobile();
        }
        if (StringUtils.isBlank(engineerPhone)) {
            xnoUnBindDTO.setBindStatus(GlobalConsts.NONE);
            return;
        }

        // 小号非绑定状态 无法解绑
        //if (orderDetail.getBindStatus() != OrderConsts.BIND_STATUS_BIND) {
        //  return;
        //}

        // 根据小号和师傅手机号查询绑定id
        Collection<AxbUnbindDIO> unBindList = Lists.newArrayList();
        if (StringUtil.isNotBlank(xnoUnBindDTO.getUnBindTelephone1())) {
            ZsXnoBindVO zsXnoBindVO = queryXNO(engineerPhone, xnoUnBindDTO.getUnBindTelephone1(), orderWork);
            if (zsXnoBindVO != null) {
                AxbUnbindDIO axbUnbindDIO = AxbUnbindDIO.builder().bindId(zsXnoBindVO.getBindId()).build();
                unBindList.add(axbUnbindDIO);
            }
        }
        if (StringUtil.isNotBlank(xnoUnBindDTO.getUnBindTelephone2())) {
            ZsXnoBindVO zsXnoBindVO = queryXNO(engineerPhone, xnoUnBindDTO.getUnBindTelephone2(), orderWork);
            if (zsXnoBindVO != null) {
                AxbUnbindDIO axbUnbindDIO2 = AxbUnbindDIO.builder().bindId(zsXnoBindVO.getBindId()).build();
                unBindList.add(axbUnbindDIO2);
            }
        }
        if (StringUtil.isNotBlank(xnoUnBindDTO.getUnBindTelephone3())) {
            ZsXnoBindVO zsXnoBindVO = queryXNO(engineerPhone, xnoUnBindDTO.getUnBindTelephone3(), orderWork);
            if (zsXnoBindVO != null) {
                AxbUnbindDIO axbUnbindDIO3 = AxbUnbindDIO.builder().bindId(zsXnoBindVO.getBindId()).build();
                unBindList.add(axbUnbindDIO3);
            }
        }

        // 不需要解绑
        if (CollectionUtils.isEmpty(unBindList)) {
            xnoUnBindDTO.setBindStatus(GlobalConsts.NONE);
            return;
        }

        log.info("XnoBind-工单【{}】小号解绑入参 :{}", xnoUnBindDTO.getOrderId(), unBindList);
        ResponseDTO<Collection<AxbUnbindDRO>> unbindResponse = axbBindRemoteService.unbind(unBindList);
        log.info("XnoBind-工单【{}】小号解绑出参 :{}", xnoUnBindDTO.getOrderId(), JSONObject.toJSONString(unbindResponse));
        if (unbindResponse.getData() == null || !unbindResponse.isSuccess()) {
            throw new OmsBaseException(unbindResponse.getMessage());
        }
    }

    /**
     * 查询绑定小号相关信息
     *
     * @return
     */
    @Override
    public ZsXnoBindVO queryXNO(String masterMobile, String telephone, OrderWork orderWork) {
        try {
            // 判断电话是否是座机 如果是则在电话前拼接区号
            String code = "";
            ResponseDTO<AreaDRO> byId = areaListRemoteService.getById(orderWork.getCityId());
            if (byId.isSuccess() && byId.getData() != null) {
                code = byId.getData().getAreaNum();
            }
            return this.queryXNO(masterMobile, telephone, code, orderWork);
        } catch (Exception e) {
            log.info("XnoBind-小号查询异常：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 查询小号绑定关系
     *
     * @param masterMobile
     * @param telephone
     * @param code
     * @param orderWork
     * @return
     */
    private ZsXnoBindVO queryXNO(String masterMobile, String telephone, String code, OrderWork orderWork) {
        try {
            // 判断电话是否是座机 如果是则在电话前拼接区号
            boolean fixedPhone = MobileUtil.isFixedPhone(telephone);
            telephone = fixedPhone ? code + telephone : telephone;

            AxbBindIdXnoQueryDIO axbBindIdXnoQueryDIO = AxbBindIdXnoQueryDIO.builder().bizId(orderWork.getOrderId().toString()).ano(masterMobile).bno(telephone).appKey("oms").plat(orderWork.getPlatWork()).build();
            log.info("XnoBind-查询绑定信息入参：{}", JSONObject.toJSONString(axbBindIdXnoQueryDIO));
            ResponseDTO<XnoBind> xnoBindResponseDTO = axbBindRemoteService.queryBindIdAndXno(axbBindIdXnoQueryDIO);
            log.info("XnoBind-查询绑定信息出参：{}", xnoBindResponseDTO.toString());
            if (!xnoBindResponseDTO.isSuccess() || xnoBindResponseDTO.getData() == null) {
                log.info("XnoBind-查询小号绑定id失败 :{}", JSONObject.toJSONString(xnoBindResponseDTO));
                return null;
            }
            XnoBind xnoBind = xnoBindResponseDTO.getData();
            return BeanMapper.map(xnoBind, ZsXnoBindVO.class);
        } catch (Exception e) {
            log.info("小号查询异常：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 查询解绑小号相关信息
     *
     * @return
     */
    @Override
    public ZsXnoBindVO queryUnBindXNO(String masterMobile, String telephone, OrderWork orderWork) {

        try {
            // 判断电话是否是座机 如果是则在电话前拼接区号
            String code = "";
            ResponseDTO<AreaDRO> byId = areaListRemoteService.getById(orderWork.getCityId());
            if (byId.isSuccess() && byId.getData() != null) {
                code = byId.getData().getAreaNum();
            }
            boolean fixedPhone = MobileUtil.isFixedPhone(telephone);
            telephone = fixedPhone ? code + telephone : telephone;

            AxbBindIdXnoQueryDIO axbBindIdXnoQueryDIO = AxbBindIdXnoQueryDIO.builder().bizId(orderWork.getOrderId().toString()).ano(masterMobile).bno(telephone).appKey("oms").plat(orderWork.getPlatWork()).build();
            log.info("XnoBind-查询解绑信息入参：{}", JSONObject.toJSONString(axbBindIdXnoQueryDIO));
            ResponseDTO<XnoBind> xnoBindResponseDTO = axbBindRemoteService.queryLastestBindIdAndXno(axbBindIdXnoQueryDIO);
            log.info("XnoBind-查询解绑信息出参：{}", xnoBindResponseDTO.toString());
            if (!xnoBindResponseDTO.isSuccess() || xnoBindResponseDTO.getData() == null) {
                log.info("XnoBind-查询解绑小号绑定id失败 :{}", JSONObject.toJSONString(xnoBindResponseDTO));
                return null;
            }
            XnoBind xnoBind = xnoBindResponseDTO.getData();
            return BeanMapper.map(xnoBind, ZsXnoBindVO.class);
        } catch (Exception e) {
            log.info("XnoBind-解绑小号查询异常：{}", e.getMessage());
            return null;
        }
    }


    /**
     * 小号延绑
     *
     * @return
     */
    @Override
    public Boolean delayBind(List<DelayBindDTO> delayBindDTOS) {
        try {
            Collection<AxbDelayBindDIO> collection = BeanMapper.mapList(delayBindDTOS, AxbDelayBindDIO.class);
            log.info("XnoBind-延绑接口入参：{}", collection);
            ResponseDTO<Collection<AxbDelayBindDRO>> collectionResponseDTO = axbBindRemoteService.delayBind(collection);
            log.info("XnoBind-延绑接口出参：{}", JSONObject.toJSONString(collectionResponseDTO));
            return collectionResponseDTO.isSuccess() && collectionResponseDTO.getData() != null;
        } catch (Exception e) {
            log.info("XnoBind-延绑接口异常：{}", e.getMessage());
            return false;
        }
    }

    /**
     * 检查是否需要重新绑定小号
     *
     * @param xnoUnBindDTO
     * @return
     */
    @Override
    public Boolean checkNeedRebind(XnoUnBindDTO xnoUnBindDTO) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(xnoUnBindDTO.getOrderId(), xnoUnBindDTO.getWorkId());
        log.info("workId={} 检查是否需要重新绑定小号 工单状态{}", xnoUnBindDTO.getWorkId(), orderWork.getStatus());
        if (orderWork.getStatus() >= OrderStatusConsts.WORK_STATUS_DISTRIBUTE &&
                Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            return true;
        }
        return false;
    }
}
